package com.yuzhi.common.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.Arrays;
import java.util.stream.IntStream;

/**
 * @ClassName: SoilPhEnum
 * @Author: Mario
 * @Date: 2024-08-18 15:04
 * @Description: 土壤酸碱度枚举值
 * @ProjectName: drainageapp-area
 * @PackageName: com.yu—zhi.common.enums
 */
@Getter
@AllArgsConstructor
public enum SoilPhEnum {
    NEUTRAL("中性", new double[][]{
            {6.0, 6.5},
            {6.5, 7.5}
    }, new boolean[][]{
            // 6.0 <= ph < 6.5
            {true, false},
            // 6.5 <= ph < 7.5
            {true, false}
    }, 100),
    SLIGHTLY_ACIDIC_OR_ALKALINE("弱酸碱性", new double[][]{
            {5.5, 6.0},
            {7.5, 8.5}
    }, new boolean[][]{
            // 5.5 <= ph < 6.0
            {true, false},
            // 7.5 <= ph < 8.5
            {true, false}
    }, 80),
    STRONGLY_ACIDIC_OR_ALKALINE("强酸碱性", new double[][]{
            {4.5, 5.5},
            {8.5, 9.5}
    }, new boolean[][]{
            // 4.5 <= ph < 5.5
            {true, false},
            // 8.5 <= ph < 9.5
            {true, false}
    }, 60),
    EXTREMELY_ACIDIC_OR_ALKALINE("极强酸碱性", new double[][]{
            {Double.NEGATIVE_INFINITY, 4.5},
            {9.5, Double.POSITIVE_INFINITY}
    }, new boolean[][]{
            // -∞ < ph < 4.5
            {false, false},
            // 9.5 <= ph < ∞
            {true, false}
    }, 40);


    private final String desc;

    private final double[][] ranges;

    private final boolean[][] includeBounds;

    private final double calculationValue;

    public static double getCalculationValue(double phValue) {
        return Arrays.stream(values())
                .filter(f -> f.isWithinRange(phValue))
                .findFirst()
                .map(SoilPhEnum::getCalculationValue)
                .orElseThrow(() -> new IllegalArgumentException("Invalid soil pH value"));
    }

    /**
     * 判断是否在范围内
     * @param phValue
     * @return boolean
     * @date: 2024-08-18 15:29:57
     * @author: Mario
     */
    public boolean isWithinRange(double phValue) {
        return IntStream.range(0, ranges.length).anyMatch(m -> isInRange(phValue, ranges[m], includeBounds[m]));
    }

    /**
     * 判断 pH 值是否在给定的范围内
     * @param phValue
     * @param range
     * @param includeBound
     * @return boolean
     */
    private boolean isInRange(double phValue, double[] range, boolean[] includeBound) {
        boolean leftCheck = includeBound[0] ? phValue >= range[0] : phValue > range[0];
        boolean rightCheck = includeBound[1] ? phValue <= range[1] : phValue < range[1];
        return leftCheck && rightCheck;
    }
}
